!     Copyright (C) 2010 Benjamin Piaud
!
!     LIMBES is free software; you can redistribute it and/or modify
!     it under the terms of the GNU General Public License as published by
!     the Free Software Foundation; either version 3, or (at your option)
!     any later version.

!     LIMBES is distributed in the hope that it will be useful,
!     but WITHOUT ANY WARRANTY; without even the implied warranty of
!     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!     GNU General Public License for more details.

!     You should have received a copy of the GNU General Public License
!     along with LIMBES; if not, see <http://www.gnu.org/licenses/>


!     all common variables of the LIMBES kernel begin by LIMBES_

module LIMBES_mod_var

  !     mesh informations
  integer*8, allocatable :: LIMBES_cell_ni(:,:)
  integer*8, allocatable :: LIMBES_cell_xi(:)
  integer*8, allocatable :: LIMBES_cell_yi(:)
  integer*8, allocatable :: LIMBES_neighbour_RLUD(:,:)

  !    Discrete Velocities Model (dvm) parameters
  integer*8 :: LIMBES_nv,LIMBES_NH
  integer*8, allocatable :: LIMBES_opposite_v(:)
  integer*8, allocatable :: LIMBES_opposite_vx(:)
  integer*8, allocatable :: LIMBES_opposite_vy(:)
  real*8, allocatable :: LIMBES_vx(:),LIMBES_vy(:)
  !     quadrature weights
  real*8, allocatable :: LIMBES_w(:)
  real*8, allocatable :: LIMBES_feq0(:)

  !     distribution functions
  real*8, allocatable :: LIMBES_f(:,:)
  real*8, allocatable :: LIMBES_feq(:,:)
  real*8, allocatable :: LIMBES_f_1wall(:,:)
  real*8, allocatable :: LIMBES_f_2wall(:,:,:)
  real*8, allocatable :: LIMBES_coll(:,:)
  real*8, allocatable :: LIMBES_vgradf(:,:)

  !     macroscopic fields
  real*8, allocatable :: LIMBES_rho(:)
  real*8, allocatable :: LIMBES_ux(:)
  real*8, allocatable :: LIMBES_uy(:)
  real*8, allocatable :: LIMBES_RT(:)

  !     macroscopic invariant sum over space
  real*8, allocatable :: LIMBES_sum_rho(:)
  real*8, allocatable :: LIMBES_sum_ux(:)
  real*8, allocatable :: LIMBES_sum_uy(:)
  real*8, allocatable :: LIMBES_sum_RT(:)

  !     transport scheme choice
  character*20 :: LIMBES_transport_scheme

contains
  subroutine init_LIMBES_var(nx,ny,ncell,nv,nsavetime)
    implicit none
    integer*8 :: ncell,nv,nx,ny,nsavetime,izero
    real*8 :: zero
    parameter(zero=0.0D+0,izero=0)
    allocate(LIMBES_cell_ni(1:nx,1:ny))
    LIMBES_cell_ni=izero
    allocate(LIMBES_cell_xi(1:ncell))
    LIMBES_cell_xi=izero
    allocate(LIMBES_cell_yi(1:ncell))
    LIMBES_cell_yi=izero
    allocate(LIMBES_neighbour_RLUD(1:ncell,1:4))
    LIMBES_neighbour_RLUD=izero
    allocate(LIMBES_opposite_v(1:nv))
    LIMBES_opposite_v=izero
    allocate(LIMBES_opposite_vx(1:nv))
    LIMBES_opposite_vx=izero
    allocate(LIMBES_opposite_vy(1:nv))
    LIMBES_opposite_vy=izero
    allocate(LIMBES_vx(1:nv))
    LIMBES_vx=zero
    allocate(LIMBES_vy(1:nv))
    LIMBES_vy=zero
    allocate(LIMBES_w(1:nv))
    LIMBES_w=zero
    allocate(LIMBES_feq0(1:nv))
    LIMBES_feq0=zero
    allocate(LIMBES_f(1:ncell,1:nv))
    LIMBES_f=zero    
    allocate(LIMBES_feq(1:ncell,1:nv))
    LIMBES_feq=zero
    allocate(LIMBES_coll(1:ncell,1:nv))
    LIMBES_coll=zero
    allocate(LIMBES_vgradf(1:ncell,1:nv))
    LIMBES_vgradf=zero
    allocate(LIMBES_rho(1:ncell))
    LIMBES_rho=zero
    allocate(LIMBES_ux(1:ncell))
    LIMBES_ux=zero
    allocate(LIMBES_uy(1:ncell))
    LIMBES_uy=zero
    allocate(LIMBES_RT(1:ncell))
    LIMBES_RT=zero
    allocate(LIMBES_sum_rho(0:nsavetime))
    LIMBES_sum_rho=zero
    allocate(LIMBES_sum_ux(0:nsavetime))
    LIMBES_sum_ux=zero
    allocate(LIMBES_sum_uy(0:nsavetime))
    LIMBES_sum_uy=zero
    allocate(LIMBES_sum_RT(0:nsavetime))
    LIMBES_sum_RT=zero
  end subroutine init_LIMBES_var
  !---------------------------------------------------------------------------
  subroutine init_LIMBES_var_wall(n1wall,n2wall,nv)
    implicit none
    integer*8 :: n1wall,n2wall,nv
    real*8 :: zero
    parameter(zero=0.0D+0)
    allocate(LIMBES_f_1wall(1:n1wall,1:nv))
    LIMBES_f_1wall=zero
    allocate(LIMBES_f_2wall(1:n2wall,1:nv,1:2))
    LIMBES_f_2wall=zero
  end subroutine init_LIMBES_var_wall
  !---------------------------------------------------------------------------
  subroutine free_LIMBES_var()
    implicit none   
    deallocate(LIMBES_cell_ni)
    deallocate(LIMBES_cell_xi)
    deallocate(LIMBES_cell_yi)
    deallocate(LIMBES_neighbour_RLUD)
    deallocate(LIMBES_opposite_v)
    deallocate(LIMBES_opposite_vx)
    deallocate(LIMBES_opposite_vy)
    deallocate(LIMBES_vx)
    deallocate(LIMBES_vy)
    deallocate(LIMBES_w)
    deallocate(LIMBES_feq0)
    deallocate(LIMBES_f)
    deallocate(LIMBES_feq)
    deallocate(LIMBES_coll)
    deallocate(LIMBES_vgradf)
    deallocate(LIMBES_rho)
    deallocate(LIMBES_ux)
    deallocate(LIMBES_uy)
    deallocate(LIMBES_RT)
    deallocate(LIMBES_sum_rho)
    deallocate(LIMBES_sum_ux)
    deallocate(LIMBES_sum_uy)
    deallocate(LIMBES_sum_RT)
  end subroutine free_LIMBES_var

  !---------------------------------------------------------------------------
  subroutine check_init_LIMBES_var()
    implicit none
    if (.NOT.allocated(LIMBES_cell_ni)) print*,'LIMBES_cell_ni not allocated'
    if (.NOT.allocated(LIMBES_cell_xi)) print*,'LIMBES_cell_xi not allocated'
    if (.NOT.allocated(LIMBES_cell_yi)) print*,'LIMBES_cell_yi not allocated'
    if (.NOT.allocated(LIMBES_neighbour_RLUD)) print*,'LIMBES_neighbour_RLUD not allocated'
    if (.NOT.allocated(LIMBES_opposite_v)) print*,'LIMBES_oppposite_v not allocated'
    if (.NOT.allocated(LIMBES_opposite_vx)) print*,'LIMBES_oppposite_vx not allocated'
    if (.NOT.allocated(LIMBES_opposite_vy)) print*,'LIMBES_oppposite_vy not allocated'
    if (.NOT.allocated(LIMBES_vx)) print*,'(LIMBES_vx not allocated'
    if (.NOT.allocated(LIMBES_vy)) print*,'(LIMBES_vy not allocated'
    if (.NOT.allocated(LIMBES_w)) print*,'(LIMBES_w not allocated'
    if (.NOT.allocated(LIMBES_feq0)) print*,'(LIMBES_feq0 not allocated'
    if (.NOT.allocated(LIMBES_f)) print*,'(LIMBES_f not allocated'
    if (.NOT.allocated(LIMBES_feq)) print*,'(LIMBES_feq not allocated'
    if (.NOT.allocated(LIMBES_coll)) print*,'LIMBES_coll not allocated'
    if (.NOT.allocated(LIMBES_vgradf)) print*,'LIMBES_vgradf not allocated'
    if (.NOT.allocated(LIMBES_rho)) print*,'LIMBES_rho not allocated'
    if (.NOT.allocated(LIMBES_ux)) print*,'LIMBES_ux not allocated'
    if (.NOT.allocated(LIMBES_uy)) print*,'LIMBES_uy not allocated'
    if (.NOT.allocated(LIMBES_RT)) print*,'LIMBES_RT not allocated'
    if (.NOT.allocated(LIMBES_sum_rho)) print*,'LIMBES_sum_rho not allocated'
    if (.NOT.allocated(LIMBES_sum_ux)) print*,'LIMBES_sum_ux not allocated'
    if (.NOT.allocated(LIMBES_sum_uy)) print*,'LIMBES_sum_uy not allocated'
    if (.NOT.allocated(LIMBES_sum_RT)) print*,'LIMBES_sum_RT not allocated'
  end subroutine check_init_LIMBES_var
  !---------------------------------------------------------------------------
  integer  function strlen(st)
    integer :: i
    character :: st*(*)
    i=len(st)
    do while (st(i:i).eq.' ')
       i=i-1
    enddo
    strlen=i
    return
  end function strlen

  !---------------------------------------------------------------------------
  integer*8 function intlen(n)
    implicit none
    integer*8 :: i,n,nlen

    i=n
    nlen=1
    do while(i.GE.10)
       i=i/10
       nlen=nlen+1
    enddo
    intlen=nlen
  end function intlen
end module LIMBES_mod_var


